package com.example.service.impl;

import com.example.common.Result;
import com.example.common.PageResult;
import com.example.dto.RechargeDTO;
import com.example.dto.RechargeRecordQueryDTO;
import com.example.entity.RechargeRecord;
import com.example.entity.User;
import com.example.mapper.RechargeRecordMapper;
import com.example.mapper.UserMapper;
import com.example.service.RechargeService;
import com.example.service.UserBalanceService;
import com.example.util.JwtUserUtil;
import com.example.vo.RechargeRecordVO;
import com.example.vo.UserBalanceVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;

@Slf4j
@Service
public class RechargeServiceImpl implements RechargeService {
    
    @Autowired
    private RechargeRecordMapper rechargeRecordMapper;
    
    @Autowired
    private UserMapper userMapper;
    
    @Autowired
    private UserBalanceService userBalanceService;

    @Autowired
    private JwtUserUtil jwtUserUtil;
    
    @Override
    @Transactional
    public Result<String> recharge(Long userId, RechargeDTO rechargeDTO) {
        try {
            // 验证用户ID
            if (userId == null) {
                return Result.error("用户未登录");
            }

            // 获取用户信息
            User user = userMapper.selectById(userId);
            if (user == null) {
                return Result.error("用户不存在");
            }
            
            // 获取充值前余额
            Result<UserBalanceVO> balanceResult = userBalanceService.getUserBalance(userId);
            if (!balanceResult.isSuccess()) {
                return Result.error("获取用户余额失败");
            }
            UserBalanceVO userBalance = balanceResult.getData();
            BigDecimal beforeBalance = userBalance.getBalance();
            
            // 生成订单号
            String orderNo = generateOrderNo();
            
            // 创建充值记录
            RechargeRecord rechargeRecord = new RechargeRecord();
            rechargeRecord.setUserId(userId);
            rechargeRecord.setUsername(user.getUsername());
            rechargeRecord.setRechargeAmount(rechargeDTO.getRechargeAmount());
            rechargeRecord.setBeforeBalance(beforeBalance);
            rechargeRecord.setAfterBalance(beforeBalance.add(rechargeDTO.getRechargeAmount()));
            rechargeRecord.setRechargeType(rechargeDTO.getRechargeType());
            rechargeRecord.setPaymentMethod(rechargeDTO.getPaymentMethod());
            rechargeRecord.setOrderNo(orderNo);
            rechargeRecord.setStatus(1); // 成功状态
            rechargeRecord.setRemark(rechargeDTO.getRemark());
            rechargeRecord.setCreateTime(LocalDateTime.now());
            rechargeRecord.setUpdateTime(LocalDateTime.now());
            rechargeRecord.setDeleted(0);
            
            // 保存充值记录
            rechargeRecordMapper.insert(rechargeRecord);
            
            // 更新用户余额
            Result<Void> updateResult = userBalanceService.updateBalanceAndTotalRecharge(userId, rechargeDTO.getRechargeAmount());
            if (!updateResult.isSuccess()) {
                throw new RuntimeException("更新用户余额失败");
            }
            
            log.info("用户充值成功，用户ID: {}, 充值金额: {}, 订单号: {}", userId, rechargeDTO.getRechargeAmount(), orderNo);
            return Result.success(orderNo);
        } catch (Exception e) {
            log.error("用户充值失败，用户ID: {}, 充值金额: {}", userId, rechargeDTO.getRechargeAmount(), e);
            return Result.error("充值失败：" + e.getMessage());
        }
    }

    @Override
    public Result<String> userRecharge(RechargeDTO rechargeDTO) {
        try {
            // 从当前请求上下文获取用户ID
            Long userId = jwtUserUtil.getCurrentUserIdFromContext();
            if (userId == null) {
                return Result.error("用户未登录");
            }

            return recharge(userId, rechargeDTO);
        } catch (Exception e) {
            log.error("用户充值失败", e);
            return Result.error("充值失败：" + e.getMessage());
        }
    }
    
    @Override
    @Transactional
    public Result<String> adminRecharge(Long adminUserId, String adminUsername, RechargeDTO rechargeDTO) {
        try {
            // 验证管理员信息
            if (adminUserId == null || adminUsername == null) {
                return Result.error("管理员未登录");
            }

            // 验证目标用户ID
            if (rechargeDTO.getTargetUserId() == null) {
                return Result.error("目标用户ID不能为空");
            }

            // 获取目标用户信息
            User targetUser = userMapper.selectById(rechargeDTO.getTargetUserId());
            if (targetUser == null) {
                return Result.error("目标用户不存在");
            }
            
            // 获取充值前余额
            Result<UserBalanceVO> balanceResult = userBalanceService.getUserBalance(rechargeDTO.getTargetUserId());
            if (!balanceResult.isSuccess()) {
                return Result.error("获取用户余额失败");
            }
            UserBalanceVO userBalance = balanceResult.getData();
            BigDecimal beforeBalance = userBalance.getBalance();
            
            // 生成订单号
            String orderNo = generateOrderNo();
            
            // 创建充值记录
            RechargeRecord rechargeRecord = new RechargeRecord();
            rechargeRecord.setUserId(rechargeDTO.getTargetUserId());
            rechargeRecord.setUsername(targetUser.getUsername());
            rechargeRecord.setRechargeAmount(rechargeDTO.getRechargeAmount());
            rechargeRecord.setBeforeBalance(beforeBalance);
            rechargeRecord.setAfterBalance(beforeBalance.add(rechargeDTO.getRechargeAmount()));
            rechargeRecord.setRechargeType("ADMIN");
            rechargeRecord.setPaymentMethod(rechargeDTO.getPaymentMethod());
            rechargeRecord.setOrderNo(orderNo);
            rechargeRecord.setStatus(1); // 成功状态
            rechargeRecord.setRemark(rechargeDTO.getRemark());
            rechargeRecord.setOperatorId(adminUserId);
            rechargeRecord.setOperatorName(adminUsername);
            rechargeRecord.setCreateTime(LocalDateTime.now());
            rechargeRecord.setUpdateTime(LocalDateTime.now());
            rechargeRecord.setDeleted(0);
            
            // 保存充值记录
            rechargeRecordMapper.insert(rechargeRecord);
            
            // 更新用户余额
            Result<Void> updateResult = userBalanceService.updateBalanceAndTotalRecharge(rechargeDTO.getTargetUserId(), rechargeDTO.getRechargeAmount());
            if (!updateResult.isSuccess()) {
                throw new RuntimeException("更新用户余额失败");
            }
            
            log.info("管理员充值成功，管理员ID: {}, 目标用户ID: {}, 充值金额: {}, 订单号: {}",
                    adminUserId, rechargeDTO.getTargetUserId(), rechargeDTO.getRechargeAmount(), orderNo);
            return Result.success(orderNo);
        } catch (Exception e) {
            log.error("管理员充值失败，管理员ID: {}, 目标用户ID: {}, 充值金额: {}",
                    adminUserId, rechargeDTO.getTargetUserId(), rechargeDTO.getRechargeAmount(), e);
            return Result.error("充值失败：" + e.getMessage());
        }
    }

    @Override
    public Result<String> adminRecharge(RechargeDTO rechargeDTO) {
        try {
            // 从当前请求上下文获取管理员信息
            Long adminUserId = jwtUserUtil.getCurrentUserIdFromContext();
            String adminUsername = jwtUserUtil.getCurrentUsernameFromContext();

            if (adminUserId == null || adminUsername == null) {
                return Result.error("管理员未登录");
            }

            return adminRecharge(adminUserId, adminUsername, rechargeDTO);
        } catch (Exception e) {
            log.error("管理员充值失败", e);
            return Result.error("充值失败：" + e.getMessage());
        }
    }
    
    @Override
    public Result<RechargeRecordVO> getRechargeRecordByOrderNo(String orderNo) {
        try {
            RechargeRecord rechargeRecord = rechargeRecordMapper.selectByOrderNo(orderNo);
            if (rechargeRecord == null) {
                return Result.error("充值记录不存在");
            }
            
            // 转换为VO（这里简化处理，实际可以使用工具类转换）
            RechargeRecordVO vo = convertToVO(rechargeRecord);
            return Result.success(vo);
        } catch (Exception e) {
            log.error("根据订单号查询充值记录失败，订单号: {}", orderNo, e);
            return Result.error("查询充值记录失败");
        }
    }
    
    @Override
    public Result<PageResult<RechargeRecordVO>> getUserRechargeRecords(Long userId, int page, int size) {
        try {
            // 验证用户ID
            if (userId == null) {
                return Result.error("用户未登录");
            }

            RechargeRecordQueryDTO queryDTO = new RechargeRecordQueryDTO();
            queryDTO.setUserId(userId);
            queryDTO.setPage(page);
            queryDTO.setSize(size);

            return getRechargeRecordPage(queryDTO);
        } catch (Exception e) {
            log.error("查询用户充值记录失败，用户ID: {}", userId, e);
            return Result.error("查询充值记录失败");
        }
    }

    @Override
    public Result<PageResult<RechargeRecordVO>> getMyRechargeRecords(int page, int size) {
        try {
            // 从当前请求上下文获取用户ID
            Long userId = jwtUserUtil.getCurrentUserIdFromContext();
            if (userId == null) {
                return Result.error("用户未登录");
            }

            return getUserRechargeRecords(userId, page, size);
        } catch (Exception e) {
            log.error("查询当前用户充值记录失败", e);
            return Result.error("查询充值记录失败");
        }
    }
    
    @Override
    public Result<PageResult<RechargeRecordVO>> getMyRechargeRecords(int page, int size, RechargeRecordQueryDTO queryDTO) {
        try {
            // 从当前请求上下文获取用户ID
            Long userId = jwtUserUtil.getCurrentUserIdFromContext();
            log.info("=== 查询充值记录 === 用户ID: {}, 页码: {}, 大小: {}", userId, page, size);

            if (userId == null) {
                log.warn("用户未登录，无法查询充值记录");
                return Result.error("用户未登录");
            }

            // 设置用户ID和分页参数
            queryDTO.setUserId(userId);
            queryDTO.setPage(page);
            queryDTO.setSize(size);

            log.info("查询参数: {}", queryDTO);
            Result<PageResult<RechargeRecordVO>> result = getRechargeRecordPage(queryDTO);
            log.info("查询结果: 总数={}, 当前页数据量={}",
                result.getData() != null ? result.getData().getTotal() : 0,
                result.getData() != null && result.getData().getRecords() != null ? result.getData().getRecords().size() : 0);

            return result;
        } catch (Exception e) {
            log.error("查询当前用户充值记录失败", e);
            return Result.error("查询充值记录失败");
        }
    }
    
    @Override
    public Result<PageResult<RechargeRecordVO>> getRechargeRecordPage(RechargeRecordQueryDTO queryDTO) {
        try {
            int offset = (queryDTO.getPage() - 1) * queryDTO.getSize();
            
            // 查询数据
            List<RechargeRecordVO> records = rechargeRecordMapper.selectVOPage(queryDTO, offset, queryDTO.getSize());
            
            // 查询总数
            long total = rechargeRecordMapper.selectCountByQuery(queryDTO);
            
            PageResult<RechargeRecordVO> pageResult = new PageResult<>();
            pageResult.setRecords(records);
            pageResult.setTotal(total);
            pageResult.setCurrent(queryDTO.getPage());
            pageResult.setSize(queryDTO.getSize());
            
            return Result.success(pageResult);
        } catch (Exception e) {
            log.error("分页查询充值记录失败", e);
            return Result.error("查询充值记录失败");
        }
    }
    
    @Override
    public Result<Map<String, Object>> getRechargeStatistics() {
        try {
            Map<String, Object> statistics = new HashMap<>();
            
            // 今日充值统计
            BigDecimal todayTotal = rechargeRecordMapper.selectTodayTotalRecharge();
            long todayCount = rechargeRecordMapper.selectTodayTotalCount();
            
            statistics.put("todayTotalAmount", todayTotal);
            statistics.put("todayTotalCount", todayCount);
            
            return Result.success(statistics);
        } catch (Exception e) {
            log.error("获取充值统计信息失败", e);
            return Result.error("获取充值统计信息失败");
        }
    }
    
    @Override
    public Result<Map<String, Object>> getUserRechargeStatistics(Long userId) {
        try {
            // 验证用户ID
            if (userId == null) {
                return Result.error("用户未登录");
            }

            Map<String, Object> statistics = new HashMap<>();

            // 用户总充值金额（成功的充值）
            BigDecimal totalAmount = rechargeRecordMapper.selectTotalRechargeByUserIdAndStatus(userId, 1);
            
            // 用户总充值次数（成功的充值）
            RechargeRecordQueryDTO queryDTO = new RechargeRecordQueryDTO();
            queryDTO.setUserId(userId);
            queryDTO.setStatus(1);
            long totalCount = rechargeRecordMapper.selectCountByQuery(queryDTO);
            
            // 计算成功率
            RechargeRecordQueryDTO allQueryDTO = new RechargeRecordQueryDTO();
            allQueryDTO.setUserId(userId);
            long allCount = rechargeRecordMapper.selectCountByQuery(allQueryDTO);
            
            double successRate = allCount > 0 ? (double) totalCount / allCount * 100 : 0;

            statistics.put("totalAmount", totalAmount != null ? totalAmount : BigDecimal.ZERO);
            statistics.put("totalCount", totalCount);
            statistics.put("successRate", Math.round(successRate * 100.0) / 100.0); // 保留两位小数
            statistics.put("totalRecharge", totalAmount != null ? totalAmount : BigDecimal.ZERO); // 兼容旧字段

            return Result.success(statistics);
        } catch (Exception e) {
            log.error("获取用户充值统计信息失败，用户ID: {}", userId, e);
            return Result.error("获取用户充值统计信息失败");
        }
    }

    @Override
    public Result<Map<String, Object>> getMyRechargeStatistics() {
        try {
            // 从当前请求上下文获取用户ID
            Long userId = jwtUserUtil.getCurrentUserIdFromContext();
            if (userId == null) {
                return Result.error("用户未登录");
            }

            return getUserRechargeStatistics(userId);
        } catch (Exception e) {
            log.error("获取当前用户充值统计信息失败", e);
            return Result.error("获取用户充值统计信息失败");
        }
    }
    
    @Override
    public Result<Map<String, Object>> getTodayRechargeStatistics() {
        try {
            Map<String, Object> statistics = new HashMap<>();
            
            BigDecimal todayTotal = rechargeRecordMapper.selectTodayTotalRecharge();
            long todayCount = rechargeRecordMapper.selectTodayTotalCount();
            
            statistics.put("totalAmount", todayTotal);
            statistics.put("totalCount", todayCount);
            
            return Result.success(statistics);
        } catch (Exception e) {
            log.error("获取今日充值统计失败", e);
            return Result.error("获取今日充值统计失败");
        }
    }
    
    @Override
    public Result<Map<String, Object>> getRechargeStatisticsByDateRange(String startTime, String endTime) {
        try {
            Map<String, Object> statistics = new HashMap<>();
            
            BigDecimal totalAmount = rechargeRecordMapper.selectTotalRechargeByDateRange(startTime, endTime);
            long totalCount = rechargeRecordMapper.selectTotalCountByDateRange(startTime, endTime);
            
            statistics.put("totalAmount", totalAmount);
            statistics.put("totalCount", totalCount);
            statistics.put("startTime", startTime);
            statistics.put("endTime", endTime);
            
            return Result.success(statistics);
        } catch (Exception e) {
            log.error("根据时间范围获取充值统计失败，开始时间: {}, 结束时间: {}", startTime, endTime, e);
            return Result.error("获取充值统计失败");
        }
    }
    
    @Override
    @Transactional
    public Result<Void> updateRechargeStatus(String orderNo, Integer status, String remark) {
        try {
            RechargeRecord rechargeRecord = rechargeRecordMapper.selectByOrderNo(orderNo);
            if (rechargeRecord == null) {
                return Result.error("充值记录不存在");
            }
            
            rechargeRecord.setStatus(status);
            rechargeRecord.setRemark(remark);
            rechargeRecord.setUpdateTime(LocalDateTime.now());
            
            rechargeRecordMapper.updateById(rechargeRecord);
            
            log.info("更新充值记录状态成功，订单号: {}, 状态: {}", orderNo, status);
            return Result.success();
        } catch (Exception e) {
            log.error("更新充值记录状态失败，订单号: {}, 状态: {}", orderNo, status, e);
            return Result.error("更新充值记录状态失败");
        }
    }
    
    /**
     * 生成订单号
     */
    private String generateOrderNo() {
        String timestamp = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss"));
        String uuid = UUID.randomUUID().toString().replace("-", "").substring(0, 8);
        return "RC" + timestamp + uuid.toUpperCase();
    }
    
    /**
     * 转换为VO对象
     */
    private RechargeRecordVO convertToVO(RechargeRecord rechargeRecord) {
        RechargeRecordVO vo = new RechargeRecordVO();
        vo.setId(rechargeRecord.getId());
        vo.setUserId(rechargeRecord.getUserId());
        vo.setUsername(rechargeRecord.getUsername());
        vo.setRechargeAmount(rechargeRecord.getRechargeAmount());
        vo.setBeforeBalance(rechargeRecord.getBeforeBalance());
        vo.setAfterBalance(rechargeRecord.getAfterBalance());
        vo.setRechargeType(rechargeRecord.getRechargeType());
        vo.setPaymentMethod(rechargeRecord.getPaymentMethod());
        vo.setOrderNo(rechargeRecord.getOrderNo());
        vo.setTransactionId(rechargeRecord.getTransactionId());
        vo.setStatus(rechargeRecord.getStatus());
        vo.setRemark(rechargeRecord.getRemark());
        vo.setOperatorId(rechargeRecord.getOperatorId());
        vo.setOperatorName(rechargeRecord.getOperatorName());
        vo.setCreateTime(rechargeRecord.getCreateTime());
        vo.setUpdateTime(rechargeRecord.getUpdateTime());
        return vo;
    }
}
